package dk.au.cs.bdsi.core.representation;

import java.net.URI;
import java.net.URISyntaxException;

/**
 * A Unique Resource Identification for Services within this application. Encompasses common
 * behavior (features) which makes sense for services (such as {@link ServiceUri#getId()}.
 */
public class ServiceUri {
	/**
	 * This is the name under which this Application is to be deployed in an
	 * Application Server, Servlet container or similar. This is used to construct
	 * the correct Base URI's for this service.<br/>
	 * If left blank ("") or as null, it is assumed that this application is being run
	 * as the ROOT application.
	 */
	public final static String ApplicationDeploymentPath = "services";
    private URI uri;
    
    public ServiceUri(String uri) {
        try {
            this.uri = new URI(uri);
        } catch (URISyntaxException e) {
            throw new RuntimeException(e);
        }
    }
    
    public ServiceUri(URI uri) {
        this(uri.toString());
    }

    public ServiceUri(URI uri, Identifier identifier) {
        this(uri.toString() + "/" + identifier.toString());
    }

    public Identifier getId() {
        String path = uri.getPath();
        return new Identifier(path.substring(path.lastIndexOf("/") + 1, path.length()));
    }

    public URI getFullUri() {
        return uri;
    }
    
    @Override
	public String toString() {
        return uri.toString();
    }
    
    @Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((uri == null) ? 0 : uri.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		ServiceUri other = (ServiceUri) obj;
		if (uri == null) {
			if (other.uri != null)
				return false;
		} else if (!uri.toString().equals(other.uri.toString()))
			return false;
		return true;
	}
	
	private String baseUriCache = null;
    public String getBaseUri() {
    	if (baseUriCache == null) {
    		/*
    		 * We choose not to synchronize the build process of the Base URI
    		 * as the penalty for synchronizing is higher than that of building
    		 * the same cache multiple times.
    		 */
	    	StringBuilder str = new StringBuilder();
	    	// Base part
	    	str.append(uri.getScheme())
	    		.append("://")
	    		.append(uri.getHost());
	    	
	    	// Optional port number
	    	if (uri.getPort() != 80 && uri.getPort() != -1) {
	    		str.append(":")
	    			.append(uri.getPort());
	    	}
	    	
	    	// Optional application name
	    	if (ApplicationDeploymentPath != null && !ApplicationDeploymentPath.isEmpty()) {
	    		str.append('/')
	    			.append(ApplicationDeploymentPath);
	    	}
	    	
	    	// Update cache
	    	baseUriCache = str.toString();
    	}
    	
    	
    	return baseUriCache;
    	
//        String port = "";
//        if(uri.getPort() != 80 && uri.getPort() != -1) {
//            port = ":" + String.valueOf(uri.getPort());
//        }
//        
//        return uri.getScheme() + "://" + uri.getHost() + port;
    }
}
